package cn.ycc1.baseset.classes;

/**
 * Classes and Objects
 * This part of the tutorial covers the basics of class definition, object creation, nesting classes,
 * enumerations, declaring member variables, methods, and constructors.
 * @author ycc
 * @date 2025/3/4
 * Creating and Using Objects
 */
public class Objects {

    /**
     * Understanding What Objects Are
     * @param args
     * A typical Java program creates many objects, which as you know, interact by invoking methods.
     * Through these object interactions, a program can carry out various tasks, such as implementing a GUI,
     * running an animation, or sending and receiving information over a network. Once an object has completed
     * the work for which it was created, its resources are recycled for use by other objects.
     *
     * Here is a small program, called CreateObjectDemo, that creates three objects: one Point object and two Rectangle objects.
     * You will need all three source files to compile this program.
     *
     * This program creates, manipulates, and displays information about various objects. Here's the output:
     *
     * Width of rectOne: 100
     * Height of rectOne: 200
     * Area of rectOne: 20000
     * X Position of rectTwo: 23
     * Y Position of rectTwo: 94
     * X Position of rectTwo: 40
     * Y Position of rectTwo: 72
     * The following three sections use the above example to describe the life cycle of an object within a program.
     * From them, you will learn how to write code that creates and uses objects in your own programs.
     * You will also learn how the system cleans up after an object when its life has ended.
     */
    public static void main(String[] args) {

        // Declare and create a point object and two rectangle objects.
        Point originOne = new Point(23, 94);
        Rectangle rectOne = new Rectangle(originOne, 100, 200);
        Rectangle rectTwo = new Rectangle(50, 100);

        // display rectOne's width, height, and area
        System.out.println("Width of rectOne: " + rectOne.width);
        System.out.println("Height of rectOne: " + rectOne.height);
        System.out.println("Area of rectOne: " + rectOne.getArea());

        // set rectTwo's position
        rectTwo.origin = originOne;

        // display rectTwo's position
        System.out.println("X Position of rectTwo: " + rectTwo.origin.x);
        System.out.println("Y Position of rectTwo: " + rectTwo.origin.y);

        // move rectTwo and display its new position
        rectTwo.move(40, 72);
        System.out.println("X Position of rectTwo: " + rectTwo.origin.x);
        System.out.println("Y Position of rectTwo: " + rectTwo.origin.y);
    }

    /**
     * Creating Objects
     * As you know, a class provides the blueprint for objects; you create an object from a class.
     * Each of the following statements taken from the CreateObjectDemo program creates an object and assigns it to a variable:
     *
     * The first line creates an object of the Point class, and the second and third lines each create an object of the Rectangle class.
     *
     * Each of these statements has three parts (discussed in detail below):
     *
     * Declaration: The code set in bold are all variable declarations that associate a variable name with an object type.
     * Instantiation: The new keyword is a Java operator that creates the object.
     * Initialization: The new operator is followed by a call to a constructor, which initializes the new object.
     *
     * Declaring a Variable to Refer to an Object
     * Previously, you learned that to declare a variable, you write:
     *
     * type name;
     * This notifies the compiler that you will use name to refer to data whose type is type. With a primitive variable, this declaration also reserves the proper amount of memory for the variable.
     *
     * You can also declare a reference variable on its own line. For example:
     *
     * Point originOne;
     * If you declare originOne like this, its value will be undetermined until an object is actually created and assigned to it. Simply declaring a reference variable does not create an object. For that, you need to use the new operator, as described in the next section. You must assign an object to originOne before you use it in your code. Otherwise, you will get a compiler error.
     *
     * A variable in this state, currently references no object.
     *
     * Instantiating a Class 实例化一个类
     * The new operator instantiates a class by allocating memory for a new object and returning a reference to that memory.
     * The new operator also invokes the object constructor.
     *
     * Note: The phrase "instantiating a class" means the same thing as "creating an object." When you create an object,
     * you are creating an "instance" of a class, therefore "instantiating" a class.
     *
     * The new operator requires a single, postfix argument: a call to a constructor. The name of the constructor provides
     * the name of the class to instantiate.
     *
     * The new operator returns a reference to the object it created. This reference is usually assigned to a variable of
     * the appropriate type, like:
     *
     * Point originOne = new Point(23, 94);
     * The reference returned by the new operator does not have to be assigned to a variable. It can also be used directly
     * in an expression. For example:
     *
     * int height = new Rectangle().height;
     * This statement will be discussed in the next section.
     */
    Point originOne = new Point(23, 94);
    Rectangle rectOne = new Rectangle(originOne, 100, 200);
    Rectangle rectTwo = new Rectangle(50, 100);

    /**
     * Initializing an Object
     * Here is the code for the Point class:
     * This class contains a single constructor. You can recognize a constructor because its declaration uses the same
     * name as the class and it has no return type. The constructor in the Point class takes two integer arguments,
     * as declared by the code (int a, int b). The following statement provides 23 and 94 as values for those arguments:
     * Point originOne = new Point(23, 94);
     * The result of executing this statement can be illustrated in the next figure:
     * A Point Object: originOne2 ->(引用) x = 23, y = 94
     *
     * Rectangle rectOne = new Rectangle(originOne, 100, 200);
     * This calls one of Rectangle's constructors that initializes origin to originOne.
     * Also, the constructor sets width to 100 and height to 200.
     * Now there are two references to the same Point object—an object can have multiple references to it,
     * as shown in the next figure:
     *
     * The following line of code calls the Rectangle constructor that requires two integer arguments, which provide the initial values for width and height. If you inspect the code within the constructor, you will see that it creates a new Point object whose x and y values are initialized to 0:
     *
     * Rectangle rectTwo = new Rectangle(50, 100);
     * The Rectangle constructor used in the following statement does not take any arguments, so it is called a no-argument constructor:
     *
     * Rectangle rect = new Rectangle();
     * All classes have at least one constructor. If a class does not explicitly declare any,
     * the Java compiler automatically provides a no-argument constructor, called the default constructor.
     * This default constructor calls the class parent's no-argument constructor,
     * or the Object constructor if the class has no other parent. If the parent has no constructor (Object does have one),
     * the compiler will reject the program.
     */
    Point originOne2 = new Point(23, 94);

    /**
     * Using Objects
     * Once you have created an object, you probably want to use it for something. You may need to use the value of
     * one of its fields, change one of its fields, or call one of its methods to perform an action.
     *
     * Referencing an Object's Fields
     * Object fields are accessed by their name. You must use a name that is unambiguous.
     *
     * You may use a simple name for a field within its own class. For example, we can add a statement within
     * the Rectangle class that prints the width and height:
     *
     * System.out.println("Width and height are: " + width + ", " + height);
     * In this case, width and height are simple names.
     *
     * Code that is outside the object's class must use an object reference or expression, followed by the dot (.) operator,
     * followed by a simple field name, as in:
     *
     * objectReference.fieldName
     * For example, the code in the CreateObjectDemo class is outside the code for the Rectangle class.
     * So to refer to the origin, width, and height fields within the Rectangle object named rectOne,
     * the CreateObjectDemo class must use the names rectOne.origin, rectOne.width, and rectOne.height, respectively.
     * The program uses two of these names to display the width and the height of rectOne:
     *
     * System.out.println("Width of rectOne: "  + rectOne.width);
     * System.out.println("Height of rectOne: " + rectOne.height);
     * Attempting to use the simple names width and height from the code in the CreateObjectDemo class does not
     * make sense — those fields exist only within an object — and results in a compiler error.
     *
     * Later, the program uses similar code to display information about rectTwo. Objects of the same type have their
     * own copy of the same instance fields. Thus, each Rectangle object has fields named origin, width, and height.
     * When you access an instance field through an object reference, you reference that particular object's field.
     * The two objects rectOne and rectTwo in the CreateObjectDemo program have different origin, width, and height fields.
     *
     * To access a field, you can use a named reference to an object, as in the previous examples,
     * or you can use any expression that returns an object reference. Recall that the new operator returns
     * a reference to an object. So you could use the value returned from new to access a new object's fields:
     *
     * int height = new Rectangle().height;
     * This statement creates a new Rectangle object and immediately gets its height. In essence(本质上),
     * the statement calculates the default height of a Rectangle. Note that after this statement has been executed,
     * the program no longer has a reference to the created Rectangle, because the program never stored the reference anywhere.
     * The object is unreferenced, and its resources are free to be recycled by the Java Virtual Machine.
     * 此语句创建一个新的Rectangle对象并立即获取其高度。本质上，该语句计算矩形的默认高度。请注意，执行此语句后，程序不再引用创建的Rectangle，
     * 因为程序从未将引用存储在任何地方。该对象未被引用，其资源可由Java虚拟机自由回收。
     */

    /**
     * Calling an Object's Methods
     * You also use an object reference to invoke an object's method. You append the method's simple name to the
     * object reference, with an intervening dot operator (.). Also, you provide, within enclosing parentheses,
     * any arguments to the method. If the method does not require any arguments, use empty parentheses.
     *
     * objectReference.methodName(argumentList);
     * or:
     *
     * objectReference.methodName();
     * The Rectangle class has two methods: getArea() to compute the rectangle's area and move() to change the
     * rectangle's origin. Here's the CreateObjectDemo code that invokes these two methods:
     *
     * System.out.println("Area of rectOne: " + rectOne.getArea());
     * ...
     * rectTwo.move(40, 72);
     * The first statement invokes rectOne's getArea() method and displays the results. The second line moves rectTwo
     * because the move() method assigns new values to the object's origin.x and origin.y.
     *
     * As with instance fields, objectReference must be a reference to an object. You can use a variable name,
     * but you also can use any expression that returns an object reference. The new operator returns an object reference,
     * so you can use the value returned from new to invoke a new object's methods:
     *
     * new Rectangle(100, 50).getArea()
     * The expression new Rectangle(100, 50) returns an object reference that refers to a Rectangle object.
     * As shown, you can use the dot notation to invoke the new Rectangle's getArea() method to compute the area of
     * the new rectangle.
     *
     * Some methods, such as getArea(), return a value. For methods that return a value, you can use the method invocation
     * in expressions. You can assign the return value to a variable, use it to make decisions, or control a loop.
     * This code assigns the value returned by getArea() to the variable areaOfRectangle:
     *
     * int areaOfRectangle = new Rectangle(100, 50).getArea();
     * In this case, the object that getArea() is invoked on is the rectangle returned by the constructor.
     */

    /**
     * The Garbage Collector 垃圾收集器
     * Some object-oriented languages require that you keep track of all the objects you create and that you explicitly destroy them
     * when they are no longer needed. Managing memory explicitly is tedious and error-prone.
     * The Java platform allows you to create as many objects as you want (limited, of course, by what your system can handle),
     * and you do not have to worry about destroying them. The Java runtime environment deletes objects when
     * it determines that they are no longer being used. This process is called garbage collection.
     *
     * An object is eligible for garbage collection when there are no more references to that object.
     * References that are held in a variable are usually dropped when the variable goes out of scope.
     * Or, you can explicitly drop an object reference by setting the variable to the special value null.
     * Remember that a program can have multiple references to the same object; all references to an object
     * must be dropped before the object is eligible for garbage collection.
     *
     * The Java runtime environment has a garbage collector that periodically frees the memory used by objects
     * that are no longer referenced. The garbage collector does its job automatically when it determines that
     * the time is right.
     *
     * 一些面向对象的语言要求你跟踪你创建的所有对象，并在不再需要它们时明确地销毁它们。显式管理内存既繁琐又容易出错。
     * Java平台允许您创建任意数量的对象（当然，受系统处理能力的限制），您不必担心会破坏它们。Java运行时环境在确定不再使用对象时删除这些对象。
     * 这个过程称为垃圾收集。
     * 当不再有对该对象的引用时，该对象有资格进行垃圾回收。当变量超出作用域时，变量中保存的引用通常会被删除。
     * 或者，您可以通过将变量设置为特殊值null来显式删除对象引用。记住，一个程序可以对同一个对象有多个引用；在对象符合垃圾回收条件之前，
     * 必须删除对对象的所有引用。
     * Java运行时环境有一个垃圾收集器，可以定期释放不再被引用的对象所使用的内存。当垃圾收集器确定时间合适时，它会自动完成工作。
     */

}

